package net.sansi.v3correctserver.entity.color;

import cn.hutool.core.util.StrUtil;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
import net.sansi.v3correctserver.entity.HashEquals;
import net.sansi.v3correctserver.entity.V3Cloneable;
import net.sansi.v3correctserver.util.RGBUtil;

import java.awt.*;
import java.util.Objects;

/**
 * Created by Fang
 * create time : 2024/10/31
 * IDE : IntelliJ IDEA
 * <p>
 * 三色亮度 颜色类。
 */

@Data
@AllArgsConstructor
@NoArgsConstructor
@Accessors(chain = true)
public class PhotoColor extends HashEquals implements V3Cloneable<PhotoColor> {

    /**
     * 通过 Color 构造
     *
     * @param color color
     */
    public PhotoColor(Color color) {
        this.r = color.getRed();
        this.g = color.getGreen();
        this.b = color.getBlue();
    }

    /**
     * 通过 RGB 数组 构造
     *
     * @param rgb rgb
     */
    public PhotoColor(int[] rgb) {
        this.r = rgb[0];
        this.g = rgb[1];
        this.b = rgb[2];
    }

    /**
     * 构造单一色
     *
     * @param brightness 单一色亮度
     * @param colorIdx   颜色索引
     */
    public PhotoColor(double brightness, int colorIdx) {
        if (colorIdx == 0) r = brightness;
        if (colorIdx == 1) g = brightness;
        if (colorIdx == 2) b = brightness;
    }

    /**
     * 通过 RGB 数组 构造
     *
     * @param brights RGB 数组
     */
    public PhotoColor(double[] brights) {
        this.r = brights[0];
        this.g = brights[1];
        this.b = brights[2];
    }

    // 颜色的 RGB 值
    private double r = 0;
    private double g = 0;
    private double b = 0;

    public static PhotoColor of(Color color) {
        return new PhotoColor(color);
    }

    /**
     * 将颜色转换为指定的亮度。
     *
     * @param brightness 目标亮度
     * @return this
     */
    public PhotoColor changeBright(int brightness) {
        return changeBright(brightness * 1.0);
    }

    /**
     * 将颜色转换为指定的亮度。
     *
     * @param brightness 目标亮度
     * @return this
     */
    public PhotoColor changeBright(double brightness) {
        double scale = brightness / getBrightness();
        setR(r * scale);
        setG(g * scale);
        setB(b * scale);
        return this;
    }

    /**
     * 将颜色转换为 Color 对象。
     *
     * @return Color 对象
     */
    public Color toColor() {
        return new Color(
                (int) Math.round(Math.max(Math.min(r, 255), 0)),
                (int) Math.round(Math.max(Math.min(g, 255), 0)),
                (int) Math.round(Math.max(Math.min(b, 255), 0))
        );
    }

    /**
     * 转换为CIE色坐标
     *
     * @return Cie 坐标
     */
    public CIEChroma toCIEChroma() {
        double[] cie = RGBUtil.rgbToCIE(this.r, this.g, this.b);
        return new CIEChroma(cie[0], cie[1], cie[2]);
    }

    /**
     * 做指数/对数处理
     *
     * @param exp 指数
     * @return this
     */
    public PhotoColor toExp(double exp) {
        return new PhotoColor(
                Math.pow(r, exp),
                Math.pow(g, exp),
                Math.pow(b, exp)
        );
    }


    /**
     * 获取颜色的亮度。
     *
     * @return 亮度
     */
    public double getBrightness() {
        return r + g + b;
    }

    /**
     * 获取NTSC亮度
     *
     * @return 亮度
     */
    public double getNTSCBrightness() {
        return RGBUtil.getNTSCBright(r, g, b);
    }

    /**
     * 获取颜色的亮度。
     *
     * @param colorIdx 颜色索引
     * @return 亮度
     */
    public double getBrightness(int colorIdx) {
        if (colorIdx == 0) return r;
        if (colorIdx == 1) return g;
        if (colorIdx == 2) return b;
        return getBrightness();
    }


    /**
     * 获取颜色的饱和度。
     *
     * @return 饱和度
     */
    public double getSaturation() {
        double min = Math.min(r, Math.min(g, b));
        double max = Math.max(r, Math.max(g, b));
        if (min == 0) return max == 0 ? 0 : 1;
        return (max - min) / max;
    }

    /**
     * 减去
     *
     * @param other 其他对象
     * @return this
     */
    public PhotoColor minus(PhotoColor other) {
        r = Math.max(r - other.r, 0);
        g = Math.max(g - other.g, 0);
        b = Math.max(b - other.b, 0);
        return this;
    }

    /**
     * 加上
     *
     * @param other 其他对象
     * @return this
     */
    public PhotoColor add(PhotoColor other) {
        r += other.r;
        g += other.g;
        b += other.b;
        return this;
    }

    /**
     * 转换为数组
     *
     * @return 数组
     */
    public double[] toArray() {
        return new double[]{r, g, b};
    }

    @Override
    public PhotoColor clone(boolean isDeep) {
        return new PhotoColor(r, g, b);
    }


    @Override
    public String toString() {
        return StrUtil.format("r={},g={},b={}", r, g, b);
    }


    @Override
    public boolean equals(Object obj) {
        return super.equals(obj);
    }

    @Override
    public int hashCode() {
        return Objects.hash(r, g, b);
    }
}
